# basic continuously distributed population model

def normalizeList(data):
    total = sum(data)
    for i in range(len(data)):
        data[i] /= total

class ContinuousPopulationEvolution:
    # pop: initial population expressed as a list of pairs (player, n)
    # game: function that takes two players and computes a nonnegative score for each
    def __init__(self, players, pops, game):
        self.pops = [float(x) for x in pops]
        normalizeList(self.pops)
        self.numPlayers = len(pops)
        self.comp = [[(0.0, 0.0)] * (self.numPlayers - i) for i in range(self.numPlayers)]
        for i in range(self.numPlayers):
            for j in range(i, self.numPlayers):
                self.comp[i][j - i] = game(players[i], players[j])
        print(self.comp)
                
    # simulate numRounds and return the resulting population as a list of lists
    def simulate(self, numRounds):
        result = {}
        pops = [None] * numRounds # population distribution
        popsizes = [None] * numRounds # total population -- measure of social welfare
        for round in range(numRounds):
            nextPops = [0.0] * self.numPlayers
            for i in range(self.numPlayers):
                for j in range(i, self.numPlayers):
                    weight = self.pops[i] * self.pops[j]
                    if i == j: weight *= 0.5
                    p0score, p1score = self.comp[i][j - i]
                    nextPops[i] += weight * p0score
                    nextPops[j] += weight * p1score
            popsizes[round] = [sum(nextPops)]
            normalizeList(nextPops)
            pops[round] = [x for x in nextPops]
            self.pops = nextPops
        result["pops"] = pops
        result["popsizes"] = popsizes
        result["length"] = [[numRounds]]
        return result

            